
本篇介紹 ES2018 (ES9) 提供的 async iterators (非同步迭代器)。
在 ES2015 (ES6) 引入了 iterator interface,spec 的定義如下:必須要有 next(),其回傳值必須符合 IteratorResult interface

下面是 IteratorResult interface 的定義,需有以下 property:
done:Boolean 值
next() 呼叫的結果狀態done 為 true
done 為 false
value:任何值
done 為 false,則 value 為當前迭代元素值 (iteration element value)done 為 true,則 value 則為 iterator 的回傳值 (若沒有回傳值則 value 為 undefined )
例如:建立一個 generator 函數,呼叫該 generator 函數時,會回傳 Generator 物件,此物件實作了 Iterable interface 和 Iterator interface,所以也可說是建立新的 iterator 物件,接著就可呼叫 iterator 上的 next():
function* generatorFunc() {
yield 'first';
yield 'second';
}
let iterator = generatorFunc();
console.log(iterator);
// generatorFunc {<suspended>}
console.log(iterator.next());
// {value: "first", done: false}
console.log(iterator.next());
// {value: "second", done: false}
console.log(iterator.next());
// {value: undefined, done: true}
但過去的 iterator 只適合處理同步資料,需要 I/O 存取的資料都會透過 event-based 或 streaming 非同步 API 來處理,但 iterator 不能處理非同步資料。
若是 promise 的 iterator 也不行處理,因為只能非同步處理 value,但不能非同步處理 done 狀態,也就是說下一個值根本就還沒確定,怎麼會知道有沒有 done 呢?而且 value 可能也還沒拿到。
為了給非同步資料提供通用的存取 protocol,此提案引入了 AsyncIterator interface、async iteration statement ( for-await-of ) 和 async generator function。
AsyncIterator interface 和 Iterable interface 很像,只是將 next() 回傳的值變為 IteratorResult 物件的 Promise,spec 的定義如下:

所以原本同步的 iterator 可以直接從 next() 回傳的 IteratorResult 物件拿到 value 和 done:
const { value, done } = syncIterator.next();
console.log(value);
console.log(done);
而非同步 iterator 因為是 Promise,所以可以這樣處理:
asyncIterator.next()
.then(({ value, done }) => {
console.log(value);
console.log(done);
});